(** Some sort of ROAM hybrid used to render entire planets. *)

open Vec;;
open Gl;;

(** The number of times to subdivide the lowest triangle in the
    tree; effectively, this decreases the CPU load because these
    triangles aren't considered to be part of the ROAM structure. *)
let subdivisions = 1;;

type node =
{
  left : node;
  right : node;
  bottom : node;
  level : int;
  leftChild : node option;
  rightChild : node option;

  topVertex : vec3;
  leftVertex : vec3;
  rightVertex : vec3;
};;

type diamond = 
{
  topHalf : node;
  bottomHalf : node;
};;

type roam =
{
  top : node list;
  size : float;  (** The non-hypot side of the largest triangle *)
};;

let tesselate n = 
  let max = subdivisions in
  let cont = Array.make (1 lsl max) { x = 0.0; y = 0.0; z = 0.0 } in
  let push v =
    (let i = ref 0 in
      cont.(!i) <- v;
      i := !i + 1) in
    
  let rec subdivide left top right level = 
    if level == max then
      ( push right; 
	push top;
	push left; )
    else
      let mid = midpoint left right in
	(subdivide top mid left (level + 1);
	 subdivide right mid top (level + 1)) in
    subdivide n.leftVertex n.topVertex n.rightVertex 1;;
	  

let testTesselate n =
  tesselate n;;

let renderNode n =
  glBegin cgl_line_loop;
  glVertex3f n.topVertex.x n.topVertex.y n.topVertex.z;
  glVertex3f n.leftVertex.x n.leftVertex.y n.leftVertex.z;
  glVertex3f n.rightVertex.x n.rightVertex.y n.rightVertex.z;
  glEnd () ;;

let render n =
  List.iter renderNode n;;

let makeOctahedron diam = 
  let top = { x = 0.0; y = -.diam; z = 0.0; } in
  let  bottom = { x = 0.0; y = diam; z = 0.0; } in
  let flv = { x = -.diam; y = 0.0; z = 0.0; } in
  let frv = { x = 0.0; y = 0.0; z = diam; } in
  let blv = { x = 0.0; y = 0.0; z = -.diam; } in
  let brv = { x = diam; y = 0.0; z = 0.0; } in
    
  let rec  tf = { left = tl; right = tr; bottom = bf;
	     level = 0; leftChild = None; rightChild = None;
	     topVertex = top; leftVertex = flv; rightVertex = frv; } and
      tl = { left = tb; right = tf; bottom = bl;
	     level = 0; leftChild = None; rightChild = None;
	     topVertex = top; leftVertex = blv; rightVertex = flv; } and
      tr = { left = tf; right = tb; bottom = br;
	     level = 0; leftChild = None; rightChild = None;
	     topVertex = top; leftVertex = frv; rightVertex = brv; } and
      tb = { left = tr; right = tl; bottom = bb;
	     level = 0; leftChild = None; rightChild = None;
	     topVertex = top; leftVertex = brv; rightVertex = blv; } and
      bf = { left = br; right = bl; bottom = tf;
	     level = 0; leftChild = None; rightChild = None;
	     topVertex = bottom; leftVertex = frv; rightVertex = flv; } and
      bl = { left = bf; right = bb; bottom = tl;
	     level = 0; leftChild = None; rightChild = None;
	     topVertex = bottom; leftVertex = flv; rightVertex = blv; } and
      br = { left = bb; right = bf; bottom = tr;
	     level = 0; leftChild = None; rightChild = None;
	     topVertex = bottom; leftVertex = brv; rightVertex = frv; } and
      bb = { left = br; right = bl; bottom = tb;
	     level = 0; leftChild = None; rightChild = None;
	     topVertex = bottom; leftVertex = blv; rightVertex = brv; } in
    
    [ { topHalf = tl; bottomHalf = bl; };
      { topHalf = tr; bottomHalf = br; };
      { topHalf = tb; bottomHalf = bb; };
      { topHalf = tf; bottomHalf = bf; }; ];;

    

      




